home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
libs
/
bestl232
/
!best001.c
next >
Wrap
C/C++ Source or Header
|
1994-05-13
|
28KB
|
720 lines
/*==========================================================================
*
* !BEST001.C Tuesday, April 12, 1994
*
* con_ str_ fil_ counter counter_reg dos_shell
* supplementary source file 1 for The BESTLibrary
*
* Authored independently by George Vanous
*
*==========================================================================*/
/* ------------------------------------------------------------------------ */
/* ---------------------------- INCLUDE FILES --------------------------- */
#include <dir.h>
#include <alloc.h>
#include <errno.h>
#include <stdlib.h>
#include <process.h>
#include "!bestlib.h"
/* ------------------------------------------------------------------------ */
/* ------------------------------ MESSAGES ------------------------------ */
#define MSG01 "\nThis is your first time using %s\nI, %s, hope you enjoy this program\n\n"
#define MSG02 "\n%s has been used %d time"
#define MSG03 "\nThere is %ld bytes of free RAM now available to %s\n"
#define MSG04 "\nThis copy of %s is registered to %s\n"
#define MSG05 "\nThis is the master copy of %s\nIt is registered to its author, %s\n"
#define ERR01 "\n!!! ERROR !!! I cannot find the data file %s\n"
/* ------------------------------------------------------------------------ */
/*----------------------------------------------------------------------------
* Shell to DOS.
*
* RETURNS:
* = pointer to an error message
* = NULL if no error message
*/
char *dos_shell(void)
{
int error;
char *commandpath, *textstring;
struct ffblk ffblk;
if ((commandpath = getenv("COMSPEC")) == NULL &&
(commandpath = searchpath("COMMAND.COM")) == NULL) {
if ((error = findfirst(commandpath = "COMMAND.COM", &ffblk, 0)) == NULL &&
(error = findfirst(commandpath = "C:\COMMAND.COM", &ffblk, 0)) == NULL &&
(error = findfirst(commandpath = "C:\DOS\COMMAND.COM", &ffblk, 0)) == NULL &&
(error = findfirst(commandpath = "C:\BIN\COMMAND.COM", &ffblk, 0)) == NULL) {
textstring = "Cannot find file COMMAND.COM -- initialize COMSPEC=[path]COMMAND.COM";
return( textstring );
}
}
video_set(TEXT);
error = spawnl(P_WAIT, commandpath, commandpath, NULL);
if (error == -1) {
switch(errno) {
case EINVAL : textstring = "Bad argument passed to COMMAND.COM"; break;
case E2BIG : textstring = "Too many arguments passed to COMMAND.COM"; break;
case ENOEXEC: textstring = "Internal error -- exitting strongly suggested"; break;
case ENOMEM : textstring = "Out of memory -- cannot shell to DOS"; break;
case ENOENT : textstring = "Cannot find file COMMAND.COM -- initialize COMSPEC=[path]COMMAND.COM";
}
}
else if (!error) textstring = NULL;
return( textstring );
}
/*----------------------------------------------------------------------------
* Read, print, and increment the number of program executions.
* Print a comment, depending on the current execution number.
* Print the amount of available memory.
*
* "filename" - name of the text data file to read the number of program
* executions from (this number must be the first byte)
* - writes the incremented number of executions back to the file
* "title" - name of the program
* "author" - name of the author of the program
* "msgs" - one comment will be randomly chosen from this array of
* messages
* "msg_num" - number of messages present
*
* RETURNS:
* = file handle of the opened data file
*/
FILE *fil_count(char *filename, char *title, char *author, char *msgs[], word msg_num)
{
word counter; // usage counter
FILE *f; // file handle
DASHES; // print one line of dashes
if ((f = fopen(filename, "r+b")) == NULL) {
fprintf(stderr, ERR01, filename); // file could not be opened
exit(1); // abort with ERRORLEVEL 1
}
/* the first byte of the file is the usage counter -- get it */
fread(&counter, sizeof(counter), 1, f);
/* increment the counter and print the correct message */
if (counter++ == 0)
printf(MSG01, title, author); // print "first time used" message
else {
printf(MSG02, title, counter); // print number of program uses
if (counter != 1) // if uses do not equal 1 then
printf("s"); // pluralise
}
DOUBLESPACE;
/* write the incremented counter back to the file */
rewind(f); // go to beginning of file
fwrite(&counter, sizeof(counter), 1, f);
// the "fseek" is REQUIRED for the next "fread" to work???
fseek(f, 0L, SEEK_CUR);
printf(msgs[random(msg_num)], title);
printf(MSG03, coreleft(), title); // print amount of available memory
return( f ); // return file handle
}
/*----------------------------------------------------------------------------
* Read, print, and increment the number of program executions.
* Print to whom this program is registered.
* Print the amount of available memory.
*
* "filename" - name of the text data file to read the number of program
* executions from (this number must be the first byte)
* - writes the incremented number of executions back to the file
* "title" - name of the program
* "author" - name of the author of the program
* "registree" - name of the person to whom this program is registered
*
* RETURNS:
* = file handle of the opened data file
*/
FILE *fil_count_reg(char *filename, char *title, char *author, char *registree)
{
word counter; // usage counter
FILE *f; // file handle
DASHES; // print one line of dashes
if ((f = fopen(filename, "r+b")) == NULL) {
fprintf(stderr, ERR01, filename); // file could not be opened
exit(1); // abort with ERRORLEVEL 1
}
/* the first byte of the file is the usage counter -- get it */
fread(&counter, sizeof(counter), 1, f);
/* increment the counter and print the correct message */
if (counter++ == 0)
printf(MSG01, title, author); // print "first time used" message
else {
printf(MSG02, title, counter); // print number of program uses
if (counter != 1) // if uses do not equal 1 then
printf("s"); // pluralise
}
DOUBLESPACE;
/* write the incremented counter back to the file */
rewind(f); // go to beginning of file
fwrite(&counter, sizeof(counter), 1, f);
// the "fseek" is REQUIRED for the next "fread" to work???
fseek(f, 0L, SEEK_CUR);
if (!str_cmp(author, registree)) // if this is registered to author then
printf(MSG05, title, author); // print master copy message
else // else
printf(MSG04, title, registree); // print to whom this is registered
printf(MSG03, coreleft(), title); // print amount of available memory
return( f ); // return file handle
}
/*----------------------------------------------------------------------------
* Return the length of a file, in bytes.
*
* "f" - file handle of file to return length of
*
* RETURNS:
* = length of file in bytes
*/
long fil_len(FILE *f)
{
long curpos, length;
curpos = ftell(f); // save current position
fseek(f, 0L, SEEK_END); // go to EOF
length = ftell(f); // get EOF position relative to start
fseek(f, curpos, SEEK_SET); // go back to original position
return( length ); // return length of file, in bytes
}
/*----------------------------------------------------------------------------
* Read the next string from the current file position.
*
* "size" - initial size of text input buffer
* "f" - file handle of file to read from
*
* RETURNS:
* = pointer to next string (file pointer is set to byte just beyond word)
* = NULL if no string was found (file pointer is set to EOF)
*/
char *fil_next_str(word *size, FILE *f)
{
char ch, // temporary character-holder
*text; // text input buffer
word index = 0, // index into text input buffer
size_org; // original initial size of buffer
text = (char *) malloc(size_org = *size);
/* ignore initial whitespaces */
for (ch = getc(f); !is_letternum(ch) && ch != QUOTE; ch = getc(f)) {
if (ch == EOF) { // if we hit end of file
free(text); // no match was found (free up memory)
return( NULL ); // return NULL
}
}
/* read in next string */
if (ch == QUOTE) {
do {
if (ch == EOF) { // if we hit end of file
free(text); // no match was found (free up memory)
return( NULL ); // return NULL
}
while (index+2 >= *size) // allocate more memory if required
text = (char *) realloc(text, *size += size_org);
text[index++] = ch; // store next valid character
ch = getc(f); // get next character
} while (ch != QUOTE // loop until next character is a '"'
&& ch != CR && ch != LF); // or until it is a CR or LF
if (ch == QUOTE) // if the last character was a '"'
text[index++] = ch; // store it
}
else {
for ( ; is_letternum(ch); ch = getc(f) ) {
if (index+1 >= *size) // allocate more memory if required
text = (char *) realloc(text, *size += size_org);
text[index++] = ch; // store next valid character
}
}
text[index] = NULL; // end string with NULL-terminator
return( text ); // return next string
}
/*----------------------------------------------------------------------------
* Read the next word from the current file position.
*
* "size" - initial size of text input buffer
* "f" - file handle of file to read from
*
* RETURNS:
* = pointer to next word (file pointer is set to byte just beyond word)
* = NULL if no word was found (file pointer is set to EOF)
*/
char *fil_next_word(word *size, FILE *f)
{
char ch, // temporary character-holder
*text; // text input buffer
word index = 0, // index into text input buffer
size_org; // original initial size of buffer
text = (char *) malloc(size_org = *size);
/* ignore initial whitespaces */
for (ch = getc(f); !is_letter(ch); ch = getc(f) ) {
if (ch == EOF) { // if we hit end of file
free(text); // no match was found (free up memory)
return( NULL ); // return NULL
}
}
/* read in next word */
for ( ; is_letter(ch); ch = getc(f)) {
if (index+1 >= *size) // allocate more memory if required
text = (char *) realloc(text, *size += size_org);
text[index++] = ch; // store valid alphabet character
}
text[index] = NULL; // end string with NULL-terminator
return( text ); // return next word
}
/*----------------------------------------------------------------------------
* Read from the current file position upto the first occurrence of a string.
*
* "str" - string to read up to
* "size" - initial size of text input buffer
* "f" - file handle of file to read from
*
* RETURNS:
* = pointer to contents of file read in (file pointer is set to byte just
* beyond match
* = NULL if no match was found (file pointer is set to EOF)
*/
char *fil_read_to(char *str, word *size, FILE *f)
{
char ch, // temporary character holder
*text; // text input buffer
int index_str; // index into string-to-read-to
// must be integer because: fseek(f, -index_str, SEEK_CUR); (-ve seek)
word index = 0, // index into text input buffer
size_org; // original initial size of buffer
text = (char *) malloc(size_org = *size);
while (TRUE)
{
while ( (text[index++] = getc(f)) != str[0] ) {
if (text[index-1] == EOF) { // if we hit end of file
free(text); // no match was found (free up memory)
return( NULL ); // return NULL
}
if (index+1 >= *size) // allocate more memory if required
text = (char *) realloc(text, *size += size_org);
}
if (str_len(str) == 1) {
text[1] = NULL; // end string with NULL-terminator
return( text ); // return pointer to text input holder
}
else {
for (index_str = 0; (ch = getc(f)) == str[++index_str]; );
if (index_str == str_len(str)) { // if we found the string
fseek(f, -1, SEEK_CUR); // rewind to byte just after match
if (index+index_str > *size) // allocate more memory if required
text = (char *) realloc(text, *size = index_str+index);
str_copy(text + index, str+1);
return( text ); // return pointer to text input holder
}
else if (ch == EOF) { // if we hit end of file
free(text); // no match was found (free up memory)
return( NULL ); // return NULL
}
}
fseek(f, -index_str, SEEK_CUR); // false alarm -- rewind
}
}
/*----------------------------------------------------------------------------
* Read from the current file position upto the first occurrence of a string.
* All comments (beginning with a ';'), blank lines, and extra spaces are
* stripped to conserve memory.
*
* "str" - string to read up to
* "size" - initial size of text input buffer
* "f" - file handle of file to read from
*
* RETURNS:
* = pointer to contents of file read in (file pointer is set to byte just
* beyond match
* = NULL if no match was found (file pointer is set to EOF)
*/
char *fil_read_to_strip(char *str, word *size, FILE *f)
{
char ch, // temporary character holder
*text; // text input buffer
int index_str, // index into string-to-read-to
quotes = FALSE; // [inside a quote?] flag
word index = 0, // generic buffer character index
size_org, // original initial size of buffer
spaces = 1; // count of ' ' (space) characters
text = (char *) malloc(size_org = *size);
while (TRUE)
{
do {
ch = getc(f); // get next character
while (TRUE)
{
if (ch != ' ') spaces = 0; // reset space counter
if (ch == '[') {
if (!quotes) quotes = 2;
break;
}
if (ch == ']') {
if (quotes == 2) quotes = FALSE;
break;
}
if (ch == '"') {
if (!quotes) quotes = 1;
else if (quotes == 1) quotes = FALSE;
break;
}
if (ch == CR) {
// clear out all following CR/LF pairs
for (ch = getc(f), ch = getc(f); ch == CR || ch == LF; ch = getc(f));
quotes = FALSE, spaces = 1;
if (index) { // if not first character
text[index++] = LF; // store one EOL character
if (index+1 >= *size) // allocate more memory if required
text = (char *) realloc(text, *size += size_org);
}
continue; // check out new character
}
if (!quotes) {
if (ch == ';') { // remove all comments
if (text[index-1] == ' ')
index--;
while ((ch = getc(f)) != CR && ch != EOF);
continue; // check out new character
}
if (ch == '=') { // ignore empty spaces surrounding '='
if (text[index-1] == ' ')
index--;
spaces = 1; // if it is a space, will remove it
break; // go store '='
}
if (ch == ' ' && ++spaces > 1) { // ignore 2+ blank spaces
while ((ch = getc(f)) == ' ');
continue; // check out new character
}
}
if (ch == EOF) { // if we hit end of file
free(text); // no match was found (free up memory)
return( NULL ); // return NULL
}
break; // character is valid, so go store it
}
text[index++] = ch; // store valid character
if (index+1 >= *size) // allocate more memory if required
text = (char *) realloc(text, *size += size_org);
} while (ch != str[0]);
if (str_len(str) == 1) {
text[1] = NULL; // end string with NULL-terminator
return( text ); // return pointer to text input holder
}
else {
for (index_str = 0; (ch = getc(f)) == str[++index_str]; );
if (index_str == str_len(str)) { // if we found the string
fseek(f, -1, SEEK_CUR); // rewind to byte just after match
if (index+index_str > *size) // allocate more memory if required
text = (char *) realloc(text, *size = index_str+index);
str_copy(text + index, str+1);
return( text ); // return pointer to text input holder
}
else if (ch == EOF) { // if we hit end of file
free(text); // no match was found (free up memory)
return( NULL ); // return NULL
}
}
fseek(f, -index_str, SEEK_CUR); // false alarm -- rewind
}
}
/*----------------------------------------------------------------------------
* Search a file for a string and set the file pointer just past it.
*
* "str" - string to skip past
* "f" - file handle of file to read from
*
* RETURNS:
* The file pointer is set to one byte beyond the match or
* to the end-of-file if no match was found.
* = number of bytes scanned upto (and including) last byte of match
* = FALSE if no match was found
*/
word fil_skip_past(char *str, FILE *f)
{
int index; // input string character index
char ch; // temporary character holder
word offset = 0; // file character offset
while (TRUE)
{
for (offset++; (ch = getc(f)) != str[0]; offset++)
if (ch == EOF) return( FALSE );
if (str_len(str) == 1)
return( offset );
else {
for (index = 0, offset++; (ch = getc(f)) == str[++index]; offset++);
if (index == str_len(str)) { // if we found the string
fseek(f, -1, SEEK_CUR); // rewind to byte just after match
return( offset-1 ); // return ending offset of find
}
else if (ch == EOF) // if we hit end of file
return( FALSE ); // return FALSE
}
fseek(f, -index, SEEK_CUR); // false alarm -- rewind
offset -= index; // false alarm -- rewind
}
}
/*----------------------------------------------------------------------------
* Search a file for a string and set the file pointer to it.
*
* "str" - string to set file pointer to
* "f" - file handle of file to read from
*
* RETURNS:
* The file pointer is set to the first byte of the first match
* the end-of-file if no match was found.
* = number of bytes scanned upto (and including) first byte of match
* file pointer set to the first byte of match
* = FALSE if no match was found
* file pointer set to end-of-file
*/
word fil_skip_to(char *str, FILE *f)
{
int index; // input string character index
char ch; // temporary character holder
word offset = 0; // file character offset
while (TRUE)
{
for (offset++; (ch = getc(f)) != str[0]; offset++)
if (ch == EOF) return( FALSE );
if (str_len(str) == 1) {
fseek(f, -1, SEEK_CUR); // rewind to beginning of match
return( offset );
}
else {
for (index = 0, offset++; (ch = getc(f)) == str[++index]; offset++);
if (index == str_len(str)) { // if we found the string
fseek(f, -(index+1), SEEK_CUR); // rewind to first byte of match
return( offset-index ); // return beginning offset of find
}
else if (ch == EOF) // if we hit end of file
return( FALSE ); // return FALSE
}
fseek(f, -index, SEEK_CUR); // false alarm -- rewind
offset -= index; // false alarm -- rewind
}
}
/*----------------------------------------------------------------------------
* Return the next string from a string in memory.
*
* "text" - string to get the next string from
*
* RETURNS:
* = pointer to next string
*/
char *str_next_str(char *text)
{
char *str; // string to return
word begin, // offset to beginning of next word
index; // index into string to read from
/* ignore initial whitespaces */
for (index = 0; !is_letternum(text[index]) && text[index] != QUOTE; index++)
if (!text[index]) return( NULL ); // if we hit end of string, return NULL
/* get length of next word */
begin = index; // save offset to beginning of nextword
if (text[index] == QUOTE) {
while (TRUE) {
if (!text[index]) // if we hit end of string
return( NULL ); // return NULL
if (text[++index] == QUOTE) { // if next character is a '"'
index++; // make sure the end quote is stored
break; // break out of loop
}
if (text[index] == CR ||
text[index] == LF) // if we hit end of line
break; // break out of loop
}
}
else
while (is_letternum(text[++index]));
/* allocate memory and make copy of the word */
str = (char *) malloc(index-begin + 1);
mem_copy(str, text+begin, index-begin);
str[index-begin] = NULL; // end string with NULL-terminator
return( str ); // return next string
}
/*----------------------------------------------------------------------------
* Return the next word from a string in memory.
*
* "text" - string to get the next word from
*
* RETURNS:
* = pointer to next word
*/
char *str_next_word(char *text)
{
char *str; // str input buffer
word begin, // offset to beginning of next word
index; // index into string to read from
/* ignore initial whitespaces */
for (index = 0; !is_letter(text[index]); index++);
/* get length of next word */
for (begin = index; is_letter(text[++index]); );
/* allocate memory and make a copy of the word */
str = (char *) malloc(index-begin + 1);
mem_copy(str, text+begin, index-begin);
str[index-begin] = NULL; // end word with NULL-terminator
return( str ); // return next word
}
/*----------------------------------------------------------------------------
* Convert the boolean FALSE or TRUE into the string "FALSE" or "TRUE",
* respectively.
*
* "bool" - boolean to convert
*
* RETURNS:
* = "TRUE" if "bool" = TRUE
* = "FALSE" if "bool" = FALSE
*/
char *con_bool_to_str(boolean bool)
{
if (!bool) // is boolean = FALSE
return( "FALSE" ); // yes, so return "FALSE"
return( "TRUE" ); // else return "TRUE"
}
/*----------------------------------------------------------------------------
* Convert the numeric representation of a color to its string equivalent.
*
* "color" - color to convert
*
* RETURNS:
* = string representation of "color"
* = NULL if "color" is not a valid color
*/
char *con_color_to_str(byte color)
{
if (color == BLACK ) return( "BLACK" );
if (color == BLUE ) return( "BLUE" );
if (color == GREEN ) return( "GREEN" );
if (color == CYAN ) return( "CYAN" );
if (color == RED ) return( "RED" );
if (color == MAGENTA ) return( "MAGENTA" );
if (color == BROWN ) return( "BROWN" );
if (color == LIGHTGREY ) return( "LIGHTGREY" );
if (color == DARKGREY ) return( "DARKGREY" );
if (color == LIGHTBLUE ) return( "LIGHTBLUE" );
if (color == LIGHTGREEN ) return( "LIGHTGREEN" );
if (color == LIGHTCYAN ) return( "LIGHTCYAN" );
if (color == LIGHTRED ) return( "LIGHTRED" );
if (color == LIGHTMAGENTA) return( "LIGHTMAGENTA" );
if (color == YELLOW ) return( "YELLOW" );
if (color == WHITE ) return( "WHITE" );
return( NULL ); // no color matched -- return NULL
}
/*----------------------------------------------------------------------------
* Convert the string representation of a boolean value into boolean FALSE or TRUE,
* respectively.
*
* "str" - word to convert
*
* RETURNS:
* = TRUE if "str" = "TRUE"
* = FALSE if "str" = "FALSE"
* = -1 if "str" is not a valid boolean word
*/
shortint con_str_to_bool(char *str)
{
str_case_up(str); // make sure we are in uppercase
if (!str_cmp(str, "FALSE")) // is string = "FALSE"
return( FALSE ); // yes, so return FALSE
if (str_cmp(str, "TRUE")) // is string = "TRUE"
return( -1 ); // no, so return -1
return( TRUE ); // else return TRUE
}
/*----------------------------------------------------------------------------
* Convert the name of a color into its numeric equivalent.
*
* "str" - color to convert
*
* RETURNS:
* = color value
* = -1 if "str" is not a valid color
*/
shortint con_str_to_color(char *str)
{
str_case_up(str); // make sure we are in uppercase
if (!str_cmp(str, "BLACK") ) return( BLACK );
if (!str_cmp(str, "BLUE") ) return( BLUE );
if (!str_cmp(str, "GREEN") ) return( GREEN );
if (!str_cmp(str, "CYAN") ) return( CYAN );
if (!str_cmp(str, "RED") ) return( RED );
if (!str_cmp(str, "MAGENTA") ) return( MAGENTA );
if (!str_cmp(str, "BROWN") ) return( BROWN );
if (!str_cmp(str, "LIGHTGREY") ) return( LIGHTGREY );
if (!str_cmp(str, "DARKGREY") ) return( DARKGREY );
if (!str_cmp(str, "LIGHTBLUE") ) return( LIGHTBLUE );
if (!str_cmp(str, "LIGHTGREEN") ) return( LIGHTGREEN );
if (!str_cmp(str, "LIGHTCYAN") ) return( LIGHTCYAN );
if (!str_cmp(str, "LIGHTRED") ) return( LIGHTRED );
if (!str_cmp(str, "LIGHTMAGENTA")) return( LIGHTMAGENTA );
if (!str_cmp(str, "YELLOW") ) return( YELLOW );
if (!str_cmp(str, "WHITE") ) return( WHITE );
return( -1 ); // no color matched -- return -1
}
/*============================== END-OF-FILE =============================*/